package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.tess4j.Tess4jClient;
import com.heima.feign.client.ArticleFeignClient;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.mapper.WmChannelMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmSensitiveMapper;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.WmNewsAutoScanService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 自动审核业务
 */
@Service
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {

    @Autowired
    private WmNewsMapper wmNewsMapper;

    @Autowired
    private GreenTextScan textScan;

    @Autowired
    private GreenImageScan imageScan;

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private ArticleFeignClient articleFeignClient;

    @Autowired
    private WmChannelMapper wmChannelMapper;

    @Autowired
    private WmUserMapper wmUserMapper;

    @Autowired
    private WmSensitiveMapper wmSensitiveMapper;
    
    @Autowired
    private Tess4jClient tess4jClient;
    /**
     * 自媒体文章审核
     * 主方法
     *
     * @param newsId 自媒体文章id
     */
    @Override
    @Async//异步线程调用
    public void autoScanWmNews(Integer newsId) {
        try {
        //1.查询自媒体文章
        WmNews wmNews = wmNewsMapper.selectById(newsId);
        if(wmNews==null){
            return;
        }

        //1.5我们要提取文本和图片
        Map map = chouquTextAndImage(wmNews);

        //1.6 自管理敏感词文本审核
         Boolean sensitivetextFlag = sensitiveTextScan(wmNews,(String) map.get("content"));
        if(!sensitivetextFlag){
            return;
        }


        //2.文章文本审核
        Boolean textFlag = null;
            textFlag = textScanHandle(wmNews, (String) map.get("content"));

        if(!textFlag){
            return;
        }

        //3.文章图片审核
        Boolean imageFlag = null;

            imageFlag = imageScanHandle(wmNews,(List)map.get("imageList"));

        if(!imageFlag){
            return;
        }

        //4.远程调用保存三剑客的接口
        ResponseResult result = saveArticleForWmNews(wmNews);

        //5.更新wm_news表
        wmNews.setArticleId(Long.parseLong(result.getData().toString()));
        updateNews(wmNews, (short) 9,"文章发布成功");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 第六个抽取方法，自管理敏感词的过滤审核
     * @param content
     * @return
     */
    private Boolean sensitiveTextScan(WmNews wmNews,String content) {
        Boolean flag=true;
        //1.查询敏感词列表，只包含敏感词字段
        List<WmSensitive> wmSensitives = wmSensitiveMapper.selectList(null);
        List<String> sensitivesList = wmSensitives.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());

        //2.初始化敏感词列表
        SensitiveWordUtil.initMap(sensitivesList);

        //3.校验敏感词，返回map
        Map<String, Integer> matchWordsMap = SensitiveWordUtil.matchWords(content);

        //4.返回数据
        if(matchWordsMap.size()>0){
            updateNews(wmNews, (short) 2,"文章内容中有违规的内容");
            flag=false;
        }
        return flag;

    }

    /**
     * 抽取的第五个方法，保存三剑客
     * @param wmNews
     */
    private ResponseResult saveArticleForWmNews(WmNews wmNews) {

        ArticleDto dto=new ArticleDto();
        BeanUtils.copyProperties(wmNews,dto);
        dto.setLayout(wmNews.getType());

        //频道
        WmChannel wmChannel = wmChannelMapper.selectById(wmNews.getChannelId());
        if(wmChannel != null){
            dto.setChannelName(wmChannel.getName());
        }

        //作者
        dto.setAuthorId(wmNews.getUserId().longValue());
        WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());
        if(wmUser != null){
            dto.setAuthorName(wmUser.getName());
        }

        //设置文章id
        if(wmNews.getArticleId() != null){
            dto.setId(wmNews.getArticleId());
        }
        dto.setCreatedTime(new Date());
        ResponseResult result = articleFeignClient.saveArticle3(dto);
        return result;
    }

    /**
     * 第四个抽取的方法，图片审核
     * @param wmNews
     * @param imageList,存储的都是图片地址
     * @return
     */
    private Boolean imageScanHandle(WmNews wmNews, List<String> imageList) throws Exception {
        Boolean flag=true;
        //下载图片
        List<byte[]> byteList=new ArrayList<>();

        //加一个去重
        imageList=imageList.stream().distinct().collect(Collectors.toList());

        for (String path : imageList) {
            byte[] bytes = fileStorageService.downLoadFile(path);

           //执行OCR---ing---
            ByteArrayInputStream in = new ByteArrayInputStream(bytes);
            BufferedImage bufferImage= ImageIO.read(in);
            String content = tess4jClient.doOCR(bufferImage);

            //调用自管理敏感词的过滤方法
            Boolean senFlag = this.sensitiveTextScan(wmNews, content);
            if(!senFlag){
                 return false;
            }
            //执行OCR---end---
            byteList.add(bytes);

        }
        //调用图片审核接口
        Map map = imageScan.imageScan(byteList);
        if(map!=null){
            if(map.get("suggestion").equals("block")){
                //违规，修改wm_news状态,status=2
                updateNews(wmNews, (short) 2,"文章图片中有违规的内容");
                flag=false;
            }else if(map.get("suggestion").equals("review")){
                //人工，修改wm_news状态,status=3
                updateNews(wmNews, (short) 3,"文章图片中包含敏感词，需要人工审核");
                flag=false;
            }
        }
        return flag;

    }

    /**
     * 抽取的第三个，文本审核业务
     * @param wmNews
     * @param content
     * @return
     * @throws Exception
     */
    private Boolean textScanHandle(WmNews wmNews, String content) throws Exception {
        Boolean flag=true;
        //如果文本为空
        if((wmNews.getTitle()+"-"+content).equals("")){
            return flag;
        }

        Map contentMap = textScan.greeTextScan(content);
        if(contentMap!=null){
            if(contentMap.get("suggestion").equals("block")){
                //违规，修改wm_news状态,status=2
                updateNews(wmNews, (short) 2,"文章内容中有违规的内容");
                flag=false;
            }else if(contentMap.get("suggestion").equals("review")){
                //人工，修改wm_news状态,status=3
                updateNews(wmNews, (short) 3,"文章内容中包含敏感词，需要人工审核");
                flag=false;
            }
        }

        return flag;
    }

    /**
     * 第二个抽取的方法，修改wm_news状态
     */
    private void updateNews(WmNews wmNews,Short status,String msg) {
        wmNews.setStatus(status);
        wmNews.setReason(msg);
        wmNewsMapper.updateById(wmNews);
    }

    /**
     * 抽取的第一个方法，提取文本和图片
     * @param wmNews
     */
    private Map chouquTextAndImage(WmNews wmNews) {

        //声明一个字符串
        StringBuffer sb=new StringBuffer();
        //先 获取文本
        String title=wmNews.getTitle();
        sb.append(title);

        //声明一个List集合来承载封面地址
        List imageList=new ArrayList();


        //包含文本和图片
        String content = wmNews.getContent();
        List<Map> contentList = JSONArray.parseArray(content, Map.class);
        for (Map map : contentList) {
            if(map.get("type").equals("text")){
                //文本
                String value = (String) map.get("value");
                sb.append(value);
            }
            if(map.get("type").equals("image")){
                String value = (String) map.get("value");
                imageList.add(value);
            }
        }

        //封装封面图片到imageList
        String images = wmNews.getImages();
        if(images!=null){
            String[] split = images.split(",");
            imageList.addAll(Arrays.asList(split));
        }



        Map resutlMap=new HashMap();
        resutlMap.put("content",sb.toString());
        resutlMap.put("imageList",imageList);

        return resutlMap;
    }
}
